package com.mzkj.wanjulaile.mobile.api.modules.account.service;

import com.google.common.collect.Maps;
import com.mzkj.common.utils.Collections3;
import com.mzkj.common.utils.DateUtils;
import com.mzkj.common.utils.StringUtils;
import com.mzkj.wanjulaile.mobile.api.modules.account.constant.Constant;
import com.mzkj.wanjulaile.mobile.api.modules.account.entity.Account;
import com.mzkj.wanjulaile.mobile.api.modules.account.entity.BuyVip;
import com.mzkj.wanjulaile.mobile.api.modules.account.entity.VipCategory;
import com.mzkj.wanjulaile.mobile.api.modules.account.entity.VipScheme;
import com.mzkj.wanjulaile.mobile.api.modules.account.mapper.AccountMapper;
import com.mzkj.wanjulaile.mobile.api.modules.account.mapper.BuyVipMapper;
import com.mzkj.wanjulaile.mobile.api.modules.account.mapper.VipCategoryMapper;
import com.mzkj.wanjulaile.mobile.api.modules.account.mapper.VipSchemeMapper;
import com.mzkj.wanjulaile.mobile.api.modules.coupon.entity.Invite;
import com.mzkj.wanjulaile.mobile.api.modules.coupon.mapper.AccountCouponMapper;
import com.mzkj.wanjulaile.mobile.api.modules.coupon.mapper.InviteMapper;
import com.mzkj.wanjulaile.mobile.api.modules.order.entity.Order;
import com.mzkj.wanjulaile.mobile.api.modules.order.entity.OrderToy;
import com.mzkj.wanjulaile.mobile.api.modules.order.mapper.OrderMapper;
import com.mzkj.wanjulaile.mobile.api.modules.order.mapper.OrderToyMapper;
import com.mzkj.wanjulaile.mobile.api.modules.weChat.entity.NotifyReturnData;
import com.mzkj.wanjulaile.mobile.api.modules.weChat.mapper.NotifyReturnMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * accountService
 * Created by wangxw on 2016/12/12.
 */
@Service
public class BuyVipServiceImpl  implements BuyVipService {

    @Autowired
    private BuyVipMapper buyVipMapper;
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private AccountCouponMapper accountCouponMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private VipSchemeMapper vipSchemeMapper;
    @Autowired
    private VipCategoryMapper vipCategoryMapper;
    @Autowired
    private InviteMapper inviteMapper;
    @Autowired
    private NotifyReturnMapper notifyReturnMapper;
    @Autowired
    private OrderToyMapper orderToyMapper;

    public BuyVip get(String id) {
        return buyVipMapper.get(id);
    }

    public BuyVip getByPayNumber(String payNumber) {
        return buyVipMapper.getByPayNumber(payNumber);
    }

    @Transactional(readOnly = false)
    public int updatePayStatus(BuyVip buyVip) {
        return buyVipMapper.updatePayStatus(buyVip);
    }

    @Transactional(readOnly = false)
    public void save2(BuyVip buyVip){
        if(!StringUtils.isEmpty(buyVip.getId())){
            buyVip.preUpdate();
            buyVipMapper.update(buyVip);
        }else{
            buyVip.setIsNewRecord(true);
            buyVip.preInsert();
            buyVipMapper.insert(buyVip);
        }
    }


    /**
     * 生成购买vip记录
     *
     * @param buyVip
     * @return
     */
    @Transactional(readOnly = false)
    public Boolean insert(BuyVip buyVip) {
        buyVip.setIsNewRecord(true);
        buyVip.preInsert();
        buyVipMapper.insert(buyVip);
        return true;
    }

    public Map<String, Object> verifyAccount(Account account, VipScheme vipScheme, String accountCouponId) {
        Map<String, Object> map = Maps.newHashMap();
//        //周度优惠券只能用一次
//        BuyVip weekBuy = buyVipMapper.findExistUseWeekCoupon(account.getId());
//        if (weekBuy != null && vipScheme.getType().equals(Constant.WEEK_VIP) && StringUtils.isNotEmpty(accountCouponId)) {
//            map.put("weekUse", true);
//            return map;
//        }
//        map.put("weekUse", false);
//        //是否有未激活的会员记录
//        List<BuyVip> buyVips = buyVipMapper.findInactive(account.getId());
//        if (!Collections3.isEmpty(buyVips)) {
//            map.put("isCanBuy", false);
//            return map;
//        }
//        map.put("isCanBuy", true);
        //升级还是降级
        if (!account.getVipType().equals(Constant.WAN_MEMBER) &&null != account.getCurBuyVip()){
            BuyVip buyVip = buyVipMapper.get(account.getCurBuyVip().getId());
            VipScheme vipScheme1 = vipSchemeMapper.get(buyVip.getVipScheme().getId());
            if (vipScheme1.getVipCategory().getType()>vipScheme.getVipCategory().getType()){
                map.put("isDownVip",true);
                return map;
            }
        }
        map.put("isDownVip",false);
        return map;
    }

    /**
     * @param account 购买vip的账号
     * @param buyVip  vip购买记录
     */
    @Transactional
    public void setAccountInfo(Account account, BuyVip buyVip) {
        account = accountMapper.get(account);
        if (null != account.getVipType()){
            account.setVipCategory(vipCategoryMapper.getByType(account.getVipType()));
        }
        VipScheme vipScheme = vipSchemeMapper.get(buyVip.getVipScheme());
        VipCategory vipCategory = vipCategoryMapper.get(vipScheme.getVipCategory());
        account = accountMapper.get(account);
        //当前是处于会员有效期内
        if (StringUtils.isNotEmpty(account.getVipStart()) && DateUtils.compareDate(DateUtils.parseDate(account.getVipEnd()),new Date())>0){
            //有效期内
            //同星级购买 时长叠加
            if (account.getVipCategory().getStar().equals(vipCategory.getStar())) {
                Date date = setAccountVipSpan(DateUtils.parseDate(account.getVipEnd()), vipScheme);
                account.setVipEnd(DateUtils.formatDate(date));
            }else {
                //升级 折算时长
                BuyVip curBuyVip = buyVipMapper.getSimple(account.getCurBuyVip());
                Date date = setAccountUpVipSpan(account, vipScheme, null, curBuyVip.getFee());
                account.setVipEnd(DateUtils.formatDate(date));
            }
            //累加分享奖励时长
            setInviteRewardTime(account);
            //时长累加了 vip购买记录使用
            buyVip.setStatus(1);
            buyVipMapper.updateStatus(buyVip);
        }else if (StringUtils.isNotEmpty(account.getVipStart()) && DateUtils.compareDate(DateUtils.parseDate(account.getVipEnd()),new Date())<=0){
            accountMapper.setNullVipTime(account);
            account = accountMapper.get(account);
        }
        else if (account.getVipType() != 0 && StringUtils.isEmpty(account.getVipStart())){
            //买了vip 还没有下单
        }else {
            //不是vip 设置账号相关vip信息
        }
        account.setVipType(vipCategory.getType());
        account.setCurBuyVip(buyVip);
        account.setVipScheme(vipScheme);
        accountMapper.update(account);
        //已支付,将优惠券设置无效
        if(buyVip.getAccountCoupon()!=null && !StringUtils.isEmpty(buyVip.getAccountCoupon().getId()))
        accountCouponMapper.delete(buyVip.getAccountCoupon());
        //是否有未完成的最后一单 续费后更新最后一单 订单状态
        Order lastOrder = orderMapper.findLastOrderUnFinish(account.getId());
        if (lastOrder != null && lastOrder.getLastFlag().equals("1")){
            orderMapper.updateLastOrderForNormal(lastOrder.getId());
            //更新玩具状态使用中
            OrderToy orderToy=new OrderToy();
            orderToy.setToyStatus(com.mzkj.wanjulaile.mobile.api.modules.order.constant.Constant.ORDER_TOY_USING);
            orderToy.setOrderId(lastOrder.getId());
            orderToy.setType(0);
            orderToy.setUpdateDate(new Date());
            orderToyMapper.updateToyStatusByOrderId(orderToy);
        }
    }

    @Transactional
    public void syncBuyVipStatus() {
        //查询当前时间存在的所有过期且激活的vip
        List<BuyVip> buyVips = buyVipMapper.findAllDeadVip();
        //查询当前时间存在的所有该激活而未激活的vip
        List<BuyVip> unactiveVip = buyVipMapper.findAllUnactiveVip();
        for (BuyVip buyVip : buyVips) {
            //过期vip套餐的账号下有无其他未激活的vip套餐,规则允许最多有一个
            List<BuyVip> buyVipList = buyVipMapper.findInactive(buyVip.getAccount().getId());
            if (!Collections3.isEmpty(buyVipList)) {
                BuyVip inactiveBuyVip = buyVipList.get(0);
                Account account = new Account();
                account.setId(buyVip.getAccount().getId());
                account.setVipType(inactiveBuyVip.getVipScheme().getType());
                //if (inactiveBuyVip.getActiveTime() != null) {
                //    account.setVipStart(DateUtils.formatDate(inactiveBuyVip.getActiveTime()));
                //    account.setVipEnd(DateUtils.formatDate(inactiveBuyVip.getDeadTime()));
                //}
                account.setCurBuyVip(inactiveBuyVip);
                accountMapper.update(account);
            } else {
                //没有其他未激活vip 账号设置为普通会员
                Account account = buyVip.getAccount();
                account.setVipType(0);
                accountMapper.update(account);
            }
            //设置为过期
            buyVip.setActive(2);
        }
        if (!Collections3.isEmpty(buyVips)) {
            buyVipMapper.batchDeadUpdate(buyVips);
        }
        if (!Collections3.isEmpty(unactiveVip))
            buyVipMapper.batchActiveUpdate(unactiveVip);
    }

    @Transactional(readOnly = false)
    public int updateRefundStatus(String id) {
        return buyVipMapper.updateRefundStatus(id);
    }

    /**
     * 根据账号查找购买的体验vip 已过期状态(active=2)
     *
     * @param accountId
     * @return
     */
    public BuyVip findTempVipByAccountId(String accountId) {
        return buyVipMapper.findTempVipByAccountId(accountId);

    }

    /**
     * 0元周度会员 手动生成的购买记录
     *
     * @param buyVip
     */
    @Transactional
    public void createTempWeekVipBuy(BuyVip buyVip) {
        buyVip.setPayStatus(BuyVip.PAYSTATUS_PAID);
        buyVip.preInsert();
        buyVipMapper.insert(buyVip);
        //购买之后删除使用的优惠券
        accountCouponMapper.delete(buyVip.getAccountCoupon());
        //设置账号相关信息
        Account account = new Account();
        account.setId(buyVip.getAccount().getId());
        setAccountInfo(account, buyVip);
    }

    /**
     * 查找账号VIP过期时间
     *
     * @param accountId
     * @return
     */
    public Date findMaxDeadTimeByAccountId(String accountId) {
        return buyVipMapper.findMaxDeadTimeByAccountId(accountId);
    }

    /**
     * 首次下单时设置账号上的vip时效
     * @param order
     * @param account
     * @param curBuyVip
     */
    @Transactional
    public void setAccountVipActiveTime(Order order, Account account, BuyVip curBuyVip) {
        if (StringUtils.isEmpty(account.getVipStart())|| orderMapper.getLastOrder2ByAccountId(account.getId()) == null) {
            //激活时间修改为配送时间
            account.setVipStart(order.getAppointDate().substring(0,order.getAppointDate().indexOf('(')));
            //查找未使用的vip购买记录计算时效
            List<BuyVip> paidBuyVipList = buyVipMapper.findPaidListByAccountId(account.getId());
            if (!Collections3.isEmpty(paidBuyVipList)){
                BuyVip buyVip1 = paidBuyVipList.get(0);
                Date date = setAccountVipSpan(DateUtils.parseDate(account.getVipStart()), buyVip1.getVipScheme());
                account.setVipEnd(DateUtils.formatDate(date));
                for (int i=1 ;i<paidBuyVipList.size();i++){
                    VipScheme vipScheme = vipSchemeMapper.get(paidBuyVipList.get(i).getVipScheme().getId());
                    VipCategory vipCategory = vipCategoryMapper.get(vipScheme.getVipCategory());

                    VipScheme lastVipScheme = vipSchemeMapper.get(paidBuyVipList.get(i-1).getVipScheme());
                    VipCategory lastVipCategory = vipCategoryMapper.get(lastVipScheme.getVipCategory());
                    if (vipCategory.getStar().equals(lastVipCategory.getStar())) {
                        //同等级 叠加
                        Date date1 = setAccountVipSpan(DateUtils.parseDate(account.getVipEnd()), vipScheme);
                        account.setVipEnd(DateUtils.formatDate(date1));
                    }else{
                        //不同 折算
                        Date date1 = setAccountUpVipSpan(account, vipScheme,lastVipScheme, curBuyVip.getFee());
                        account.setVipEnd(DateUtils.formatDate(date1));

                    }
                }
                buyVipMapper.batchUpdateStatus(paidBuyVipList);
            }
            //查找是否有为累加到账号上的分享奖励时长
            setInviteRewardTime(account);
            //设置相应账号信息
            accountMapper.update(account);
            //首次下单标志
            order.setFirstFlag("1");
            orderMapper.updateFirstFlag(order);
        }
    }

    private void setInviteRewardTime(Account account) {
        Invite invite = new Invite();
        invite.setInvitedAccount(account);
        invite.setInviteTimeUse("0");
        List<Invite> inviteList = inviteMapper.findList(invite);
        VipCategory vipCategory = vipCategoryMapper.getByType(account.getVipType());
        if (!Collections3.isEmpty(inviteList)){
            Date date = DateUtils.parseDate(account.getVipEnd());
            for (Invite invite1 : inviteList) {
                //一星
                if (null != vipCategory && vipCategory.getStar()==1){
                    date = DateUtils.addTimeByDurationTimeUnit(DateUtils.parseDate(account.getVipEnd()), invite1.getInviteTimeUnit(), invite1.getInviteTimeDuration());
                    Integer totalShareTime = account.getTotalShareTime() == null ? 0:account.getTotalShareTime();
                    totalShareTime = DateUtils.addTimeWithDurationTimeUnit(totalShareTime,invite1.getInviteTimeUnit(), invite1.getInviteTimeDuration());
                    account.setTotalShareTime(totalShareTime);
                }
                //二星
                if (null != vipCategory && vipCategory.getStar()==2){
                    date = DateUtils.addTimeByDurationTimeUnit(DateUtils.parseDate(account.getVipEnd()), invite1.getInviteTimeUnitT(), invite1.getInviteTimeDurationT());
                    Integer totalShareTime = account.getTotalShareTime() == null ? 0:account.getTotalShareTime();
                    totalShareTime = DateUtils.addTimeWithDurationTimeUnit(totalShareTime,invite1.getInviteTimeUnitT(), invite1.getInviteTimeDurationT());
                    account.setTotalShareTime(totalShareTime);
                }
                account.setVipEnd(DateUtils.formatDate(date));
                invite1.setInviteTimeUse("1");
                inviteMapper.update(invite1);
            }
        }
    }

    //升级后的截止日
    public Date setAccountUpVipSpan(Account account, VipScheme vipScheme, VipScheme lastVipScheme, Integer oldFee) {
        VipScheme oldVipScheme = null;
        if (null != lastVipScheme){
            oldVipScheme = lastVipScheme;
        }else {
            oldVipScheme= vipSchemeMapper.get(account.getVipScheme());
        }
        //当前vipScheme剩余天数
        Long leftDays;
        if (StringUtils.isEmpty(account.getVipEnd())){
            leftDays =new Long(getVipSpan(lastVipScheme,0));
        }else{
            leftDays = DateUtils.getDistanceOfTwoDate(new Date(), DateUtils.parseDate(account.getVipEnd()));
        }
        //当前账号上的vipScheme时长
        int oldVipSpan = 0;
        //新购买vip时长
        int newVipSpan = 0;
        oldVipSpan = getVipSpan(oldVipScheme, oldVipSpan);
        newVipSpan = getVipSpan(vipScheme,newVipSpan);
        //30天一个月计算oldSpan 剩余天数leftDays可能大于oldSpan
        float leftFee = ((float) leftDays / (float) oldVipSpan) * oldFee;
        //剩余的钱能购买新vip的时长 + 本次新vip时长
        float upAddSpan =  leftFee / (float) vipScheme.getFee() * newVipSpan + newVipSpan;
        Date result = DateUtils.addDays(new Date(), (int) upAddSpan);
        return result;

    }

    private int getVipSpan(VipScheme vipScheme, int oldVipSpan) {
        if ("1".equals(vipScheme.getTimeUnit())){
            //日
            oldVipSpan = vipScheme.getDuration();
        }
        if ("2".equals(vipScheme.getTimeUnit())){
            //周
            oldVipSpan = vipScheme.getDuration() * 7;
        }
        if ("3".equals(vipScheme.getTimeUnit())){
            //月
            oldVipSpan = vipScheme.getDuration() *30;
        }
        if ("4".equals(vipScheme.getTimeUnit())){
            //年
            oldVipSpan = vipScheme.getDuration() * 365;
        }
        return oldVipSpan;
    }

    //同等级叠加后的截止日
    public Date setAccountVipSpan(Date date, VipScheme vipScheme) {
        Integer duration = vipScheme.getDuration();
        Date result = new Date();
        if (vipScheme.getTimeUnit().equals("1")){
            //日
            result = DateUtils.addDays(date, duration);
        }
        if (vipScheme.getTimeUnit().equals("2")){
            //周
            result = DateUtils.addWeeks(date,duration);
        }
        if (vipScheme.getTimeUnit().equals("3")){
            //月
            result = DateUtils.addMonths(date,duration);
        }
        if (vipScheme.getTimeUnit().equals("4")){
            //年
            result = DateUtils.addYears(date,duration);
        }
        return result;
    }

    public BuyVip findDepositByAccountId(String accountId) {
        return buyVipMapper.findDepositByAccountId(accountId);
    }

    @Override
    public List<BuyVip> findListByAccountId(String accountId) {
        return buyVipMapper.findListByAccountId(accountId);
    }

    @Override
    public BuyVip getSimple(BuyVip curBuyVip) {
        return buyVipMapper.getSimple(curBuyVip);
    }

    @Override
    @Transactional
    public void updateOrderVipInfo(Order order, Account account, BuyVip curBuyVip) {
        //更新订单支付状态
        orderMapper.updatePayStatus(order);
        //首次下单时设置账号上的vip时效
        setAccountVipActiveTime(order , account, curBuyVip);
    }

    private void addNotifyReturnData(NotifyReturnData returnData){
        // TODO 重复插入bug
        //判断支付通知是否已保存
        NotifyReturnData oldReturn = notifyReturnMapper.getByOutTradeNo(returnData.getOut_trade_no());
        if (null == oldReturn) {
            //TODO:确认是否有并发重复插入风险
            notifyReturnMapper.insert(returnData);
        }
    }

    @Override
    @Transactional
    public void updateOrderVipInfoByWXPay(Order order, Account account, BuyVip curBuyVip, NotifyReturnData returnData) {
        updateOrderVipInfo(order,account , curBuyVip);
        addNotifyReturnData(returnData);
    }

    @Override
    @Transactional
    public void updateAccountVipInfo(Account account, BuyVip buyVip,NotifyReturnData returnData) {
        buyVipMapper.updatePayStatus(buyVip);
        setAccountInfo(account,buyVip);
        addNotifyReturnData(returnData);
    }
}
